/* 
 * This file contains classes and functions needed for event handling.
 */

// ======================== EVENT ========================
// 
// Simple event class that can be extended by any attributes. 
// Its required attributes are: 
//  - type:     describes the main reason this event has been created.
//  - source:   the object that caused this event
function Event(type, source) {
    this.type = (type !== undefined) ? type : "unkown";
    this.source = (source !== undefined) ? source : null;
}

// ======================== EVENT DISPATCHER ========================
// 
// Objects that want to be notified when certain events occur can 
// register to dispatchers. These dispatchers dispatch events that are 
// supplied to them through the dispatchEvent function to all listeners 
// registered.
function EventDispatcher() {
    this.listeners = new Array();
    this.concurrentlyAdded = new Array();
    this.concurrentlyRemoved = new Array();
    this.dispatching = false;
}
EventDispatcher.prototype.registerListener = function(listener) {
    if (this.dispatching) {
        this.concurrentlyAdded.push(listener);
    } else {
        this.listeners.push(listener);
    }
};
EventDispatcher.prototype.removeListener = function(listener) {
    if (this.dispatching) {
        this.concurrentlyRemoved.push(listener);
    } else {
        this.listeners.remove(listener);
    }
};
EventDispatcher.prototype.dispatchEvent = function(event) {
    this.dispatching = true;

    for (var i = 0; i < this.listeners.length; i++) {
        this.listeners[i].handleEvent(event);
    }

    // remove listeners that are removed while dispatching
    for (var i = 0; i < this.concurrentlyRemoved.length; i++) {
        this.listeners.remove(event);
    }
    // remove listeners that are added while dispatching
    for (var i = 0; i < this.concurrentlyAdded.length; i++) {
        this.listeners.push(event);
    }

    this.dispatching = false;
};

